package com.ticket.sass.common.ticketserver.platform.cx30

import com.ticket.sass.common.ticketserver.configure.ConfigData
import mu.KotlinLogging
import org.apache.axis.client.Service
import org.apache.axis.encoding.XMLType
import org.json.XML
import java.time.Duration
import java.time.LocalDateTime
import javax.xml.namespace.QName
import javax.xml.rpc.ParameterMode

object RequestClient {
    private val logger = KotlinLogging.logger {}

    private val service = Service()

    data class Paramter(
        val name: String,
        val type: QName,
        val value: String,
    )

    fun sendXml(api: String, input: List<Paramter>): String {
        val call = service.createCall().apply {
            targetEndpointAddress = Configurer.ENDPOINT_TICKET
            operationName = QName(Configurer.NAMESPACE_TICKET, api)

            input.forEach { addParameter(it.name, it.type, ParameterMode.IN) }

            returnType = XMLType.XSD_STRING
        }
        val params = input.map { it.value }

        return wrapInvoke(call, params)
    }

    fun send(api: String, input: List<Paramter>, configData: ConfigData.CX30): String {
        val call = service.createCall().apply {
            targetEndpointAddress = Configurer.ENDPOINT_TICKET
            operationName = QName(Configurer.NAMESPACE_TICKET, api)

            addParameter("pAppCode", XMLType.XSD_STRING, ParameterMode.IN)
            addParameter("pCinemaCode", XMLType.XSD_STRING, ParameterMode.IN)
            input.forEach {
                addParameter(it.name, it.type, ParameterMode.IN)
            }
            addParameter("pCompress", XMLType.XSD_STRING, ParameterMode.IN)
            addParameter("pVerifyInfo", XMLType.XSD_STRING, ParameterMode.IN)

            returnType = XMLType.XSD_STRING
        }

        val params = mutableListOf(
            configData.appCode,     // 固定参数
            configData.cinemaCode   // 固定参数
        )
        params.addAll(input.map { it.value })   // 业务参数 - 动态
        params.add("0")                         // 固定参数 pCompress
        params.add(Configurer.generateTicketSign(configData, input.map { it.value }))   // 固定参数 pVerifyInfo

        return wrapInvoke(call, params)
    }

    /**
     * 封装 rpc 调用
     *
     * @param call      rpc客户端
     * @param params    调用参数
     *
     * @return [String]
     */
    private fun wrapInvoke(call: javax.xml.rpc.Call, params: List<String>): String {
        val beginTime = LocalDateTime.now()
        val res = call.invoke(params.toTypedArray()) as String
        val between = Duration.between(beginTime, LocalDateTime.now())

        logger.info { "请求时间：${between.toMillis()}毫秒, 请求地址：${call.operationName}，请求参数：${params.map { it }}，响应数据：${res}" }

        return XML.toJSONObject(res, true).toString(0)
    }
}